package com.youlian.cloud.gateway.filter;

import com.alibaba.arms.tracing.Span;
import com.alibaba.arms.tracing.Tracer;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.youlian.cloud.core.util.StringUtils;
import com.youlian.cloud.gateway.utils.DebugUtils;
import com.youlian.cloud.log.utils.RequestUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

/**
 * @author vangao1989
 * @Description: filter 前置过滤器
 * @date 2017年7月26日
 */
@SuppressWarnings("ALL")
@Component
public class AccessFilter extends ZuulFilter {

    private static Logger logger = LoggerFactory.getLogger(AccessFilter.class);

    @Override
    public Object run() {
        try {
            Span span = Tracer.builder().getSpan();
            String traceId = span.getTraceId();
            String rpcId = span.getRpcId();
            logger.info("--------------traceId----" + traceId + "-------------rpcId---" + rpcId + " ---------------------");
            // 将客户端的一些信息进行保存
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            if (DebugUtils.getValue(DebugUtils.OUT_REQUEST_HEADER)) {
                writeHeadLog(request);
            }

            String requestURL = request.getRequestURL().toString();
            String remoteAddr = request.getRemoteAddr();
            // 用户客户端地址
            String ip = RequestUtils.getClientIP(request);
            // 客户使用设备
            String userAgent = RequestUtils.getUserAgent(request);
            // 客户请求参数
            String body = null;
            if (HttpMethod.POST.toString().equals(request.getMethod().toUpperCase()) && request.getInputStream() != null &&
                    DebugUtils
                            .getValue
                                    (DebugUtils.OUT_REQUEST)) {
                body = IOUtils.toString(request.getInputStream());
            } else {
                body = request.getQueryString();
            }
            logger.info(request.getMethod() + " AccessFilter atlas to " + requestURL + " 前端服务器 : " + remoteAddr + " \n body : " + body + " \n " + userAgent);
            if (true) {
                // 对该请求进行路由
                ctx.setRequest(request);
                ctx.setSendZuulResponse(true);
                ctx.setResponseStatusCode(200);
                // 设值，让下一个Filter看到上一个Filter的状态
                ctx.set("isSuccess", true);
            } else {
                // 过滤该请求，不对其进行路由
                ctx.setSendZuulResponse(false);
                // 返回错误码
                ctx.setResponseStatusCode(401);
                // 返回错误内容
                ctx.setResponseBody("{\"result\":\"atlas fail!\"}");
                ctx.set("isSuccess", false);
            }
        } catch (Throwable throwable) {
            logger.error("AccessFilter fail", throwable);
        }
        logger.info(" AccessFilter Invoke OK ");
        return null;
    }

    /**
     * 打印请求中的所有header头信息
     *
     * @param request
     */
    private void writeHeadLog(HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        StringBuffer sb = new StringBuffer();
        // 遍历所有header中的所有值
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            sb.append(headerName + "=" + headerValue + " \n");
        }

        // 虽然没有必要，但是领导要求。
        logCommonHeader(request, "elabhouseid");
        logCommonHeader(request, "elabprojectname");
        logCommonHeader(request, "elabsystem");
        logCommonHeader(request, "elabEnvironment");

        logger.info("header -> " + sb.toString());
    }

    private void logCommonHeader(HttpServletRequest request, String headerName) {
        if (StringUtils.isEmpty(request.getHeader(headerName))) {
            logger.info("通用参数 : " + headerName + " : 无");
        }
    }


    @Override
    public boolean shouldFilter() {
        return true;// 是否执行该过滤器，此处为true，说明需要过滤
    }

    @Override
    public int filterOrder() {
        return 0;// 优先级为0，数字越大，优先级越低
    }

    @Override
    public String filterType() {
        return "pre";// 前置过滤器
    }
}
